package me.zhengjie

import me.zhengjie.common.utils.EncryptUtils
import me.zhengjie.common.utils.PageUtil
import me.zhengjie.common.utils.QueryHelp
import me.zhengjie.logging.slf4j.logError
import me.zhengjie.modules.monitor.service.RedisService
import me.zhengjie.modules.security.service.OnlineUserService
import me.zhengjie.modules.security.utils.JwtTokenUtil
import me.zhengjie.modules.system.domain.Role
import me.zhengjie.modules.system.repository.*
import me.zhengjie.modules.system.service.*
import me.zhengjie.modules.system.service.dto.DictDTO
import me.zhengjie.modules.system.service.dto.RoleDTO
import me.zhengjie.modules.system.service.dto.RoleQueryCriteria
import me.zhengjie.modules.system.service.dto.UserDTO
import me.zhengjie.modules.system.service.mapper.*
import io.jsonwebtoken.ExpiredJwtException
import jakarta.persistence.criteria.CriteriaBuilder
import jakarta.persistence.criteria.CriteriaQuery
import jakarta.persistence.criteria.Root
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.cache.annotation.EnableCaching
import org.springframework.data.domain.Pageable
import org.springframework.data.jpa.domain.Specification
import org.springframework.data.redis.core.RedisTemplate
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.scheduling.annotation.EnableAsync
import org.springframework.security.core.userdetails.UserDetailsService
import java.util.*
import java.util.concurrent.TimeUnit
import kotlin.collections.HashMap

@EnableAsync
@EnableCaching
@EnableConfigurationProperties
@SpringBootTest(classes = [me.zhengjie.AppRun::class],
    webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class ControllerTest {
    @Value("\${jwt.expiration}")
    private val expiration: Long = 0L

    @Value("\${jwt.online}")
    private val onlineKey: String = ""

    @Autowired
    private val userRepository: UserRepository? = null

    @Autowired
    private val userService: UserService? = null

    @Autowired
    private val userMapper: UserMapper? = null

    @Autowired
    private val roleRepository: RoleRepository? = null

    @Autowired
    private val roleService: RoleService? = null

    @Autowired
    private val roleMapper: RoleMapper? = null

    @Autowired
    private val menuRepository: MenuRepository? = null

    @Autowired
    private val menuService: MenuService? = null

    @Autowired
    private val menuMapper: MenuMapper? = null

    @Autowired
    private val deptRepository: DeptRepository? = null

    @Autowired
    private val deptService: DeptService? = null

    @Autowired
    private val deptMapper: DeptMapper? = null

    @Autowired
    private val jobRepository: JobRepository? = null

    @Autowired
    private val jobService: JobService? = null

    @Autowired
    private val jobMapper: JobMapper? = null

    @Autowired
    private val dictRepository: DictRepository? = null

    @Autowired
    private val dictService: DictService? = null

    @Autowired
    private val dictMapper: DictMapper? = null

    @Autowired
    private val dictDetailRepository: DictDetailRepository? = null

    @Autowired
    private val dictDetailService: DictDetailService? = null

    @Autowired
    private val dictDetailMapper: DictDetailMapper? = null

    @Autowired
    var redisService: RedisService? = null

    @Autowired
    var onlineUserService: OnlineUserService? =null

    @Autowired
    var userDetailsService: UserDetailsService?=null

    @Autowired
    val jwtUtil: JwtTokenUtil?=null

    @Autowired
    val redisTemplate: RedisTemplate<Any, Any> ?= null


    //测试dict字典的数据关联
    @Test
    fun dictServiceTest(){
        val dict:DictDTO? = dictService!!.findById(5L)!!
        println("dict name=${dict!!.name}")
        for (dictDetail in dict!!.dictDetails!!){
            println("")
            println("dictDetail id=${dictDetail.id}")
            println("dictDetail name=${dictDetail.label}")
            println("dictDetail value=${dictDetail.value}")
            println("")
        }
    }

    //测试从service findall到controller层返回responseEntity的每一层数据
    @Test
    fun roleServiceTest(){
        var pageable = Pageable.ofSize(10)
        val criteria = RoleQueryCriteria(null, null, null)

        val page = roleRepository!!.findAll(
            Specification { root: Root<Role?>, criteriaQuery: CriteriaQuery<*>?, criteriaBuilder: CriteriaBuilder ->
                QueryHelp.getPredicate(
                    root,
                    criteria,
                    criteriaBuilder
                )
            }, pageable!!
        )
        println("status code=${page.content.size}")
        for (role in page.content){
            println("role id=${role!!.id}")
            println("role name=${role!!.name}")
        }

       val page1 = page.map { role: Role? -> roleMapper!!.toDto(role)}
        println("page1=${page1.content.size}")
        for (roledto in page.content){
            println("roledto id=${roledto!!.id}")
            println("roledto name=${roledto!!.name}")
        }

        val page2 = PageUtil.toPage(page1)
        println("page1=${page2.size}")
        for (roledto in page2.get("content") as List<RoleDTO?>){
            println("roledto id=${roledto!!.id}")
            println("roledto name=${roledto!!.name}")
        }
        val respon=ResponseEntity(page2,HttpStatus.OK)
        println("status code=${respon.statusCode}")
        for (roledto in respon.body!!.get("content") as List<RoleDTO?>){
            println("response roledto id=${roledto!!.id}")
            println("response roledto name=${roledto!!.name}")
        }

    }
    @Test
    fun redisTemplateTest() {
        val jwtUser = userDetailsService!!.loadUserByUsername("admin")!! as JwtUser
        // 生成令牌
        //var token = jwtUtil!!.generateToken(jwtUser)
        var claims:Map<String, Any> = HashMap()
        val token: String = jwtUtil!!.doGenerateToken(claims,jwtUser.username)
        println("token = $token")
        claims = jwtUtil!!.getAllClaimsFromToken(token)

        println("claims = $claims")

        val username: String = claims.get("sub").toString()
        println("username from claims = $username")

        //保存onlineuser到redis
        val job = jwtUser.dept + "/" + jwtUser.job
        val ip = "192.168.1.1"
        val browser = "chrome"
        val address = "abcsd"
        var onlineUser: OnlineUser? = null
        try {
            onlineUser = OnlineUser(jwtUser.username, job, browser, ip, address, EncryptUtils.desEncrypt(token)!!, Date())
        } catch (e: Exception) {
            e.printStackTrace()
        }
        val key = onlineKey + token
        redisTemplate!!.opsForValue().set(key, onlineUser!!)
        redisTemplate!!.expire(onlineKey + token, expiration, TimeUnit.MILLISECONDS)

        //从redis读取onlineuser信息
        try {
            onlineUser = redisTemplate!!.opsForValue()[onlineKey + token] as OnlineUser?
        } catch (e: ExpiredJwtException) {
            logError(e.message!!)
        }
    }
    @Test
    fun UserRepositoryTest() {
        //val user: User? = userRepository!!.findByUsername("admin")
        val user: UserDTO? = userService!!.findByName("admin")!!
        println("user1 userinfo=${user!!.toString()}\n")

        //序列化与反序列化测试
        redisService!!.saveObj("test", user, 10)
        println("从redis读取的值：key=test，value="+redisService!!.getVal("test")+"\n")
        val user2: UserDTO = redisService!!.getObject("test") as UserDTO
        println("user2 从redis读取反序列化后的UserDTO对象string=${user2.toString()}\n")
        println("user2 从redis读取反序列化后的UserDTO对象JsonString=${user2.tojson()}\n")
        val user3:UserDTO = UserDTO.fromJson(user2.tojson()!!)!!
        println("user3 从redis读取反序列化后的UserDTO对象string=${user3.toString()}\n")
        println("user3 从redis读取反序列化后的UserDTO对象string=${user3.tojson()}\n")

    }

    @Test
    fun redisServiceTest(){
        //val redisService: RedisService = RedisServiceImpl()

        redisService!!.saveObj("test", "test")
        redisService!!.saveObj("test", "test", 10)
        redisService!!.saveCode("test", "test")
        redisService!!.saveCode("test", "test", 10)
        println("从redis读取的值：key=test，value="+redisService!!.getCodeVal("test"))
        println("从redis读取的值：key=test，value="+redisService!!.getVal("test"))
        redisService!!.delete("test")
        redisService!!.deleteAll()
        val lst=redisService!!.findByKey("test")
        for (item in lst){
            println("从redis读取的值：key=test，value="+item.value)
        }
    }
}